package com.gao.demo01;

//基本的卖票例子

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 真正的多线程开发，公司中的开发，降低耦合性。
 * 线程就是一个单独的资源类，没有任何附属操作！
 * 1、  属性，方法
 */
public class SaleTicketDemo01 {
    public static void main(String[] args) {
//        并发： 多个线程操作同一个资源类,把资源类丢入线程
        Ticket ticket = new Ticket();
//        @FunctionalInterface Runnable 函数式接口
//        这样写就是匿名内部类，也就是lambda表达式需要进行简化的对象
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 50; i++) {
                    ticket.sale();
//                    加入延迟放大数据争抢问题
                    try {
                        Thread.currentThread().sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        },"A").start();

//        (参数) ->{ 代码 }
        new Thread(()->{
            for (int i = 0; i < 50; i++) {
                ticket.sale();
                try {
                    Thread.currentThread().sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"B").start();

        new Thread(()->{
            for (int i = 0; i < 50; i++) {
                ticket.sale();
                try {
                    Thread.currentThread().sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"C").start();
    }
}

class Ticket {
//    属性，方法
    private int number = 50;

    Lock lock = new ReentrantLock();

//    卖票的方式
//    传统的加锁方式 synchronized 本质：队列 锁
    public synchronized void sale() {
//        JUC的加锁方式
//        加锁
        lock.lock();
        try {
//            业务代码
            if (number > 0) {
                System.out.println(Thread.currentThread().getName() + "卖出了第" + (number--) + "张票.剩余：" + number);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
//            解锁
            lock.unlock();
        }
    }
}